package game.manager 
{
	import flash.events.EventDispatcher;
	import flash.events.NetStatusEvent;
	import flash.events.TimerEvent;
	import flash.net.SharedObject;
	import flash.net.SharedObjectFlushStatus;
	import flash.system.Security;
	import flash.system.SecurityPanel;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	import flash.utils.Timer;
	import game.events.ParamEvent;
	
	/**
	 * ...
	 * @author gcxk721
	 */
	public class ResCacheManager extends EventDispatcher 
	{
		
		public static const OPEN_LOCAL_STORAGE:String = "OPEN_LOCAL_STORAGE";
		
        public static const SET_LOCAL_STORAGE:String = "SET_LOCAL_STORAGE";
		
		private static var instance : ResCacheManager;
		
		
		private const NEEDSPACE : int = 31457300;

        private var _soDic : Dictionary;
        private var _deleteList : Array;
        private var _serverName : String = null;
        private var _count : int = 0;
        private var _fileList : Array;
        private var _sharedObject : SharedObject;
        private var _lastTime : int = 0;
        private var _timer : Timer;
        private var _canCache : Boolean = false;
        private var _isInit : Boolean = false;
        private var _shareDic : Dictionary;
		
		public function ResCacheManager() 
		{
			if (instance != null)
			{
				throw new Error("single instance");
			}
			this._timer = new Timer(500);
            this._timer.addEventListener(TimerEvent.TIMER, this.timerHandler);
            this._soDic = new Dictionary();
            this._fileList = new Array();
            this._shareDic = new Dictionary();
            this._deleteList = [];
		}
		
		private function timerHandler(evt : TimerEvent):void 
		{
			var value : Object;
            if (this._canCache == false)
			{
                return;
            }
            if (this._fileList.length > 0)
			{
                value = this._fileList.shift();
                this.updateFile(value);
            }
            if (this._deleteList.length > 0)
			{
                this.deleteFile(this._deleteList.shift());
            }
		}
		
		private function replacePath(path : String):String
		{
            return path.split("/").join("-");
        }
		
		private function saveData(key : String, value : Object):void
		{
            if (this._sharedObject == null)
			{
                return;
            }
            this._sharedObject.data[key] = value;
        }
		
        public function getServerData(key : String):Object
		{
            var value : Object = this.getData(this._serverName);
            if (value == null)
			{
                return null;
            }
            return (value[key]);
        }
		
        private function deleteFile(url : String):void
		{
            try 
			{
                var shareObject : SharedObject = SharedObject.getLocal(url);
                shareObject.clear();
                var versionObj : Object = this._sharedObject.data["version"];
                delete versionObj[url];
                this._sharedObject.data["version"] = versionObj;
            } 
			catch (e:Error) 
			{
                return;
            }
        }
		
        public function setServerData(key : String, serverData:Object):void
		{
            var value : Object = this.getData(this._serverName);
            if (value == null)
			{
                value = new Object();
            }
            value[key] = serverData;
            this.saveData(this._serverName, value);
        }
		
        private function initCache():void
		{
            if (this._isInit == true)
			{
                return;
            }
            this._isInit = true;
            this._canCache = true;
            this._sharedObject.data["version"] = new Object();
            this._sharedObject.flush();
            this._timer.start();
        }
		
        public function setFile(key : String, bytes : ByteArray, isSave : Boolean = false):void
		{
            var file : Object = this.getFileObj(key);
            if (isSave == true)
			{
                this._soDic[file.url] = bytes;
            }
            if (this._canCache == false)
			{
                return;
            }
            file.data = bytes;
            this._fileList.push(file);
        }
		
        private function netStatusHandler(evt : NetStatusEvent):void
		{
            if (evt.info.code == "SharedObject.Flush.Failed")
			{
				
            } 
			else 
			{
                this.initCache();
            }
            this.dispatchEvent(new ParamEvent(SET_LOCAL_STORAGE, evt.info.code));
        }
		
        public function checkCache(serverName : String) : Boolean
		{
            this._serverName = serverName;
            //this._sharedObject = SharedObject.getLocal("yxyz/resCache");
            this._sharedObject = SharedObject.getLocal("qh/resCache");
            if (this._sharedObject.data["version"] != undefined)
			{
                this._isInit = true;
                this._canCache = true;
                this._timer.start();
                this._deleteList = this.getDeleteList();
                return true;
            }
            return false;
        }
		
        public function checkFile(key : String, isCreate : Boolean = true):Boolean
		{
            var file : Object = this.getFileObj(key);
            if (this._soDic[file.url] != null)
			{
                return true;
            }
            if (this._canCache == false)
			{
                return false;
            }
            var version : Object = this._sharedObject.data["version"];
            if (version == null)
			{
                return false;
            }
            if (version[file.url] != file.version)
			{
                return false;
            }
            return true;
        }
		
        private function updateFile(file : Object):void
		{
            var shareObject : SharedObject = null;
            //var time : int = getTimer();
            try 
			{
                shareObject = SharedObject.getLocal(file.url);
            } 
			catch (e:Error) 
			{
                return;
            }
            shareObject.data[file.url] = file.data;
            if (this._sharedObject.data["version"] == null)
			{
                this._sharedObject.data["version"] = new Object();
            }
            var versionObj : Object = this._sharedObject.data["version"];
            versionObj[file.url] = file.version;
            this._sharedObject.data["version"] = versionObj;
            /*if ((getTimer() - time) > 5)
			{
                debug((((("@超过5秒的缓存写入时间" + ",") + (getTimer() - time)) + ",") + fileObj.url));
            }*/
        }
		
        private function getDeleteList():Array
		{
            var ver : Object = this._sharedObject.data["version"];
            var values : Array = new Array();
            if (ver != null)
			{
				var obj : Object;
                for (obj in ver) 
				{
                    if (obj.indexOf(".swf") > -1)
					{
                        values.push(obj);
                    }
                }
            }
            if (values.length < 100)
			{
                return [];
            }
            return values;
        }
		
        public function get canCache():Boolean
		{
            return _canCache;
        }
		
        public function getFile(path : String,  isReflush : Boolean = true):ByteArray
		{
            var file : Object = this.getFileObj(path);
            if (this._soDic[file.url] != null)
			{
                return (this._soDic[file.url]);
            }
            if (this._canCache == false)
			{
                return null;
            }
            var ver : Object = this._sharedObject.data["version"];
            if (ver == null)
			{
                return null;
            }
            if (ver[file.url] != file.version)
			{
                return null;
            }
            var time : int = getTimer();
            var shared : SharedObject = SharedObject.getLocal(file.url);
           // if ((getTimer() - _local5) > 5){
           //     debug((((((((("@超过5秒的缓存时间" + ",") + (getTimer() - _local5)) + ",") + _local3.url) + ",") + getTimer()) + ",") + this._count));
           // }
            var bytes : ByteArray = shared.data[file.url];
            if (bytes != null && isReflush)
			{
                this._soDic[file.url] = bytes;
            }
            if (getTimer() - time > 100)
			{
                this._count = (this._count + 1);
                //debug(((((("@超过缓存时间次数" + this._count) + ",") + (getTimer() - _local5)) + ",") + (getTimer() - this._lastTime)));
                if ((getTimer() - this._lastTime) > 50000)
				{
                    this._count = 1;
                }
                this._lastTime = getTimer();
                if (this._count > 30)
				{
                    this._canCache = false;
                }
            }
            return bytes;
        }
		
        public function clearTemp():void
		{
			var key : *;
            for (key  in this._soDic) 
			{
                delete this._soDic[key];
            }
        }
		
        private function getData(key : String):Object
		{
            var obj : Object = null;
            if (this._sharedObject == null)
			{
                return null;
            }
            try 
			{
                obj = this._sharedObject.data[key];
            } 
			catch (e:Error) 
			{
                return null;
            }
            return obj;
        }
		
        public function openLimite():Boolean
		{
            try 
			{
                var state:String = this._sharedObject.flush(this.NEEDSPACE);
                if (state != SharedObjectFlushStatus.PENDING)
				{
                    initCache();
                    return true;
                }
                this.dispatchEvent(new ParamEvent(OPEN_LOCAL_STORAGE));
            } 
			catch (e:Error) 
			{
                Security.showSettings(SecurityPanel.LOCAL_STORAGE);
                this.dispatchEvent(new ParamEvent(OPEN_LOCAL_STORAGE));
            }
            this._sharedObject.addEventListener(NetStatusEvent.NET_STATUS, this.netStatusHandler);
            return false;
        }
		
        public function clearCache():void
		{
            if (this.getServerData("versionCode") == null)
			{
                this.setServerData("versionCode", 1);
            } 
			else 
			{
                var times : int  = int(this.getServerData("versionCode")) + 1;
                this.setServerData("versionCode", times);
            }
            this.flushServerData();
        }
		
        public function flushServerData():void{
            try 
			{
                this._sharedObject.addEventListener(NetStatusEvent.NET_STATUS, this.netStatusHandler);
                this._sharedObject.flush();
            } 
			catch (e:Error) 
			{
				
            }
        }
		
        public function getFileObj(path : String) : Object
		{
            var file : Object = new Object();
            var array : Array = path.split("?v=");
            if (array.length == 1)
			{
                file.version = 0;
            } 
			else 
			{
                file.version = array[1];
            }
            path = array[0];
            var index : int = path.indexOf("http://");
            if (index > -1)
			{
                file.url = path.substring(7);
            } 
			else 
			{
                file.url = path;
            }
            return file;
        }
		
		public static function getInstance() : ResCacheManager
		{
			if (instance == null)
			{
				instance = new ResCacheManager();
			}
			return instance;
		}
		
	}

}